#include <jni.h>
#include <string>
#include <android/log.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <thread>

typedef unsigned char u8;
#define READ_OPS 0x30
#define WRITE_OPS 0x31
#define DATAMAXSIZE 16
struct iiccom_info{
    u8 nr;
    u8 addr;
    u8 reg_start;
    u8 len;
    u8 data_buf[DATAMAXSIZE];
};
struct iiccom_info ops_info;

#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "deyiNDK", __VA_ARGS__))

char RESULT_OK[] = "ok";

jstring logEToJstring(JNIEnv* pEnv, const char* msg)
{
    LOGE("%s",msg);
    return pEnv->NewStringUTF(msg);
}

/**
 * 延时
 * @param msec 毫秒
 */
void delay_msec(int msec)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(msec));
}

int findDevice = -1;
extern "C" JNIEXPORT jstring JNICALL
Java_com_hyg_ndkapplication_NativeLib_openI2CDev(JNIEnv *env, jobject thiz) {
    // 打开设备节点,iiccom只支持arm64-v8a
    findDevice = open("/dev/iiccom", O_RDWR);
    if (findDevice < 0) {
        return logEToJstring(env,"can't open /dev/iiccom");
    }
    LOGE("findDevice = %d",findDevice);
    return env->NewStringUTF(RESULT_OK);
}

extern "C" JNIEXPORT jint JNICALL
Java_com_hyg_ndkapplication_NativeLib_getHeight(JNIEnv *env, jobject thiz, jint channel) {
    if(findDevice < 0){
        LOGE("findDevice < 0");
        return 641;
    }
    int ret = 1; //读写结果的错误码

    //write，片选
    ops_info.nr =7;
    ops_info.addr = 0x70;
    ops_info.reg_start = 0;
    ops_info.len=1;
    ops_info.data_buf[0] = channel;
    ret = ioctl(findDevice, WRITE_OPS, &ops_info);
//------------------------------------------------------------------------
    //read
    ops_info.nr =7;
    ops_info.addr = 0x40;
    ops_info.reg_start = 0x35;
    ops_info.len=1;
//    ops_info.data_buf=0;
    ret = ioctl(findDevice, READ_OPS, &ops_info);
//    LOGE("n.ret: %d,0x%02x, 0x%02x\n", ret, ops_info.data_buf[0], ops_info.data_buf[1]);
    if(ret != 0){
        LOGE("n.ret = %d",ret);
        return 642;
    }
    int n = ops_info.data_buf[0];

    delay_msec(10);
    ops_info.nr =7;
    ops_info.addr = 0x40;
    ops_info.reg_start = 0x5E;
    ops_info.len=2;
//    ops_info.data_buf=0;
    ret = ioctl(findDevice, READ_OPS, &ops_info);   // 再读取一个字节
//    LOGE("data.ret: %d,0x%02x, 0x%02x\n", ret, ops_info.data_buf[0], ops_info.data_buf[1]);
    if(ret != 0){
        LOGE("data.ret = %d",ret);
        return 643;
    }else if(ops_info.data_buf[0] == 0x00){ //失败
        LOGE("channel = %d, read 0x5E empty",channel);
        return 644;
    }
    int data = (ops_info.data_buf[0] << 4) + (ops_info.data_buf[1] & 0x0F);

    int height = data * 5 / 8 / (1 << n);
    LOGE("channel = %d, height = %d",channel,height);

    return height;
}

//int findDevice = -1;
//extern "C" JNIEXPORT jstring JNICALL
//Java_com_hyg_ndkapplication_NativeLib_openI2CDev(JNIEnv *env, jobject thiz) {
//    // 打开设备节点
//    findDevice = open("/dev/i2c-7", O_RDWR);
//    if (findDevice < 0) {
//        return logEToJstring(env,"can't open /dev/i2c-7");
//    }
//    LOGE("findDevice = %d",findDevice);
//    return env->NewStringUTF(RESULT_OK);
//}
//
//extern "C" JNIEXPORT jint JNICALL
//Java_com_hyg_ndkapplication_NativeLib_getHeight(JNIEnv *env, jobject thiz, jint channel) {
//    if(findDevice < 0){
//        LOGE("findDevice < 0");
//        return 641;
//    }
//
//    unsigned char buf[2] = {0x70,0x70};
//    int ret = 1; //读写结果的错误码
//
//    ioctl(findDevice, I2C_SLAVE, 0x70); // 设置从设备地址
//    ioctl(findDevice, I2C_TIMEOUT, 10);  // 设置超时
//    ioctl(findDevice, I2C_RETRIES, 3);  // 设置重试次数
//    //write，片选
//    buf[0] = channel;
//    write(findDevice, buf, 1);
//    delay_msec(10);
////------------------------------------------------------------------------
//    ioctl(findDevice, I2C_SLAVE, 0x40); // 设置从设备地址
//    ioctl(findDevice, I2C_TIMEOUT, 10);  // 设置超时
//    ioctl(findDevice, I2C_RETRIES, 3);  // 设置重试次数
//    //read
//    buf[0] = 0x35;
//    ret = write(findDevice, buf, 1);  // 先写入要读取的设备内部地址
//    if(ret == -1){ //写入失败
//        LOGE("channel = %d, write 0x35 error -1",channel);
//        return 642;
//    }
////    LOGE("write ret = %d",ret);
//    delay_msec(10);
//    read(findDevice, buf, 1);   // 再读取一个字节
////    LOGE("n: %c,0x%02x, 0x%02x\n", buf[0], buf[0], buf[1]);
//    int n = buf[0];
//
//    buf[0] = 0x5E;
//    delay_msec(10);
//    write(findDevice, buf, 1);  // 先写入要读取的设备内部地址
//    delay_msec(10);
//    read(findDevice, buf, 2);   // 再读取一个字节
////    LOGE("data: %c,0x%02x, 0x%02x\n", buf[0], buf[0], buf[1]);
//    if(buf[0] == 0x00){ //失败
//        LOGE("channel = %d, read 0x5E empty",channel);
//        return 643;
//    }
//    int data = (buf[0] << 4) + (buf[1] & 0x0F);
//
//    int height = data * 5 / 8 / (1 << n);
//    LOGE("channel = %d, height = %d",channel,height);
//
//    return height;
//}